#ifndef __PTGUI_DC_H__
#define __PTGUI_DC_H__

#include <ptgui/ptgui.h>
#include <ptgui/font.h>
#include <ptgui/surface.h>
#include <ptgui/driver.h>

struct _ptgui_gui_content
{
	ptgui_rect_t	clip_rect;

	rt_int8_t		draw_mode;
	rt_int8_t		pen_size;
	rt_int8_t		pen_shap;
	rt_int8_t		line_style;
	rt_int8_t		fill_style;

	ptgui_widget_t	*widget;	

	/* foreground and background color */
	ptgui_color_t	foreground;
	ptgui_color_t	background;

	rt_int8_t		text_mode;
	/* text align */
	rt_base_t		text_align;

	/* font */
	ptgui_font_t	*font;
};
typedef struct _ptgui_gui_content ptgui_gui_content_t;

enum ptgui_dc_type
{
	PTGUI_DC_HW,
	PTGUI_DC_BUFFER,
};

/* the abstract device context */
struct ptgui_dc
{
	/* type of device context */
	rt_uint32_t	type;

	/* interface */
	void (*draw_point)(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y);
	void (*draw_vline)(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y1, rt_int16_t y2);
	void (*draw_hline)(struct ptgui_dc *dc, rt_int16_t x1, rt_int16_t x2, rt_int16_t y);
	void (*fill_rect)(struct ptgui_dc *dc, ptgui_rect_t *rect);
	void (*blit)(struct ptgui_dc *dc, struct ptgui_point *dc_point, struct ptgui_dc *dest, ptgui_rect_t *rect);

	/* set and get color */
	void (*set_color)(struct ptgui_dc *dc, ptgui_color_t color);
	ptgui_color_t (*get_color)(struct ptgui_dc *dc);

	void (*set_bg_color)(struct ptgui_dc *dc, ptgui_color_t color);
	ptgui_color_t (*get_bg_color)(struct ptgui_dc *dc);

	/* set and get font */
	void (*set_font)(struct ptgui_dc *dc, ptgui_font_t *font);
	ptgui_font_t *(*get_font)(struct ptgui_dc *dc);
	void (*set_textalign)(struct ptgui_dc *dc, rt_int32_t align);
	rt_int32_t (*get_textalign)(struct ptgui_dc *dc);

	/* get dc visible */
	rt_bool_t (*get_visible)(struct ptgui_dc *dc);

	/* get dc rect */
	void (*get_rect)(struct ptgui_dc *dc, ptgui_rect_t *rect);

	rt_bool_t (*fini)(struct ptgui_dc *dc);
} ;

/* hardware device context */
struct ptgui_dc_hw
{
	struct ptgui_dc				parent;

	/* surface owner */
	ptgui_widget_t				*owner;

	/* visible */
	rt_bool_t					visible;

	/* display driver */
	struct ptgui_graphic_driver	*device;
};

extern ptgui_gui_content_t gui_content;
void ptgui_gc_system_init(void);

/* create a buffer dc */
struct ptgui_dc *ptgui_dc_buffer_create(rt_int16_t width, rt_int16_t height);
rt_uint8_t *ptgui_dc_buffer_get_pixel(struct ptgui_dc *dc);

/* create a hardware dc */
struct ptgui_dc *ptgui_dc_hw_create(ptgui_widget_t *owner);
struct ptgui_dc *ptgui_dc_begin_drawing(ptgui_widget_t *owner);
void ptgui_dc_end_drawing(struct ptgui_dc *dc);

/* destroy a dc */
void ptgui_dc_destory(struct ptgui_dc *dc);

void ptgui_dc_draw_point(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y);

void ptgui_dc_draw_vline(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y1, rt_int16_t y2);
void ptgui_dc_draw_hline(struct ptgui_dc *dc, rt_int16_t x1, rt_int16_t x2, rt_int16_t y);
void ptgui_dc_fill_rect(struct ptgui_dc *dc, struct ptgui_rect *rect);
void ptgui_dc_blit(struct ptgui_dc *dc, struct ptgui_point *dc_point, struct ptgui_dc *dest, ptgui_rect_t *rect);

void ptgui_dc_set_color(struct ptgui_dc *dc, ptgui_color_t color);
void ptgui_dc_set_bg_color(struct ptgui_dc *dc, ptgui_color_t color);
ptgui_color_t ptgui_dc_get_color(struct ptgui_dc *dc);

void ptgui_dc_set_font(struct ptgui_dc *dc, ptgui_font_t *font);
ptgui_font_t *ptgui_dc_get_font(struct ptgui_dc *dc);
void ptgui_dc_set_textalign(struct ptgui_dc *dc, rt_int32_t align);
rt_int32_t ptgui_dc_get_textalign(struct ptgui_dc *dc);

rt_bool_t ptgui_dc_get_visible(struct ptgui_dc *dc);
void ptgui_dc_get_rect(struct ptgui_dc *dc, ptgui_rect_t *rect);

void ptgui_dc_draw_line(struct ptgui_dc *dc, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2);
void ptgui_dc_draw_rect(struct ptgui_dc *dc, struct ptgui_rect *rect);
void ptgui_dc_draw_round_rect(struct ptgui_dc *dc, struct ptgui_rect *rect);

void ptgui_dc_draw_text(struct ptgui_dc *dc, const char *text, struct ptgui_rect *rect);
void ptgui_dc_draw_byte(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t h, const rt_uint8_t *data);
void ptgui_dc_draw_word(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t h, const rt_uint8_t *data);

void ptgui_dc_draw_border(struct ptgui_dc *dc, ptgui_rect_t *rect, rt_int16_t flag);
void ptgui_dc_draw_horizontal_line(struct ptgui_dc *dc, rt_int16_t x1, rt_int16_t x2, rt_int16_t y);
void ptgui_dc_draw_vertical_line(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y1, rt_int16_t y2);
void ptgui_dc_draw_arrow(struct ptgui_dc *dc, ptgui_rect_t *rect, rt_int16_t kind);
void ptgui_dc_draw_focus_rect(struct ptgui_dc *dc, ptgui_rect_t *rect);

void ptgui_dc_draw_polygon(struct ptgui_dc *dc, const rt_int16_t *vx, const rt_int16_t *vy, rt_int16_t count);
void ptgui_dc_fill_polygon(struct ptgui_dc *dc, const rt_int16_t *vx, const rt_int16_t *vy, rt_int16_t count);

void ptgui_dc_draw_circle(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r);
void ptgui_dc_fill_circle(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r);
void ptgui_dc_draw_arc(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r, rt_int16_t start, rt_int16_t end);

void ptgui_dc_draw_ellipse(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry);
void ptgui_dc_fill_ellipse(struct ptgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry);

#endif
